/* SQUIB - Scala's Quirky User Interface Builder 
    Copyright (C) 2008 Tim Dalton

    This library is free software you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

package tfd.scala.squib.demo.scenario

import java.awt.{BasicStroke, Color, Dimension, Font, Point, Rectangle, RenderingHints, Shape}
import java.awt.event._
import java.awt.geom.{Arc2D, Ellipse2D, Point2D}
import java.awt.image._
import javax.swing.{JFrame}
import javax.swing.SwingConstants._
import javax.swing.event._

import com.sun.scenario.scenegraph._
import com.sun.scenario.animation._

import tfd.scala.squib._
import tfd.scala.squib.event._
import tfd.scala.squib.scenario.scenegraph._
import tfd.scala.squib.scenario.scenegraph.event._
import tfd.scala.squib.scenario.scenegraph.effect.{effect, coloradjust}
import tfd.scala.squib.scenario.scenegraph.Implicits._

object SceneGraphSliders extends Application {
    text.attributesDefault = attributes(
            'font -> new Font("Courier", Font.BOLD, 24),
            'mode -> SGAbstractShape.Mode.FILL,
            'fillPaint -> Color.BLUE
    )
    
    var testImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB)
    var imageG = testImage.createGraphics()
    imageG.setColor(Color.magenta)
    imageG.drawRect(10,10,80,80)
    
    shape.attributesDefault = attributes('antiAliasingHint -> RenderingHints.VALUE_ANTIALIAS_ON)
    
    def createFill(shape2D: Shape)  
     =  shape(
              'shape -> shape2D,
              'fillPaint -> Color.black,
              'mode -> SGAbstractShape.Mode.FILL
         )
    
    def createStroke(shape2D: Shape, width:float) 
     =  shape(
             'shape -> shape2D,
             'drawStroke -> new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER),
             'drawPaint -> Color.black,
             'mode -> SGAbstractShape.Mode.STROKE
         )
    
    def P(x:Double, y:Double) = new Point2D.Double(x, y)
         
    def arcCenter(r:float, p1:Point2D, p2:Point2D) = {
       // d is the distance between p1,p2 and d2 is the distance
        // to the midpoint of that line.
        val d = p1.distance(p2)
        val d2 = d / 2.0
        // max possible value for d2 is r, when p1,p2 bisect the circle
        if (d2 > r) {
            throw new IllegalArgumentException("invalid parameters")
        }
        // dc is the distance from center of p1,p2 to the circle's 
        // center, since the circle's radius makes a right trangle with
        // dc and d2. 
        val dc = Math.sqrt((r*r) - (d2*d2))
        // x3,y3 are the coordinates of the midpoint of p1,p2 and
        // ux,uy is a unit vector perpindicular to p1,p2
        val x3 = (p1.getX() + p2.getX()) / 2.0f
        val y3 = (p1.getY() + p2.getY()) / 2.0f
        val ux = (p2.getY() - p1.getY()) / d
        val uy = (p1.getX() - p2.getX()) / d
        // The circle's center is just x3,y3 plus the ux,uy
        // scaled by dc (the distance from x3,y3 to the center)
        val cx = x3 + (ux * dc)
        val cy = y3 + (uy * dc)
        new Point2D.Double(cx, cy)
    }
    
    def createArc(r:float, p1:Point2D, p2: Point2D):Shape = {
        val c = arcCenter(r, p1, p2)
        val x1 = p1.getX() - c.getX() // p1 translated to the center
        val y1 = p1.getY() - c.getY()
        val a1 = 360.0 - Math.toDegrees(Math.atan2(y1, x1))
        val x2 = p2.getX() - c.getX() // p2 translated to the center
        val y2 = p2.getY() - c.getY()
        val a2 = 360.0 - Math.toDegrees(Math.atan2(y2, x2))
        val x = (c.getX() - r) // origin of the arc's bounding
        val y = (c.getY() - r) // rectangle
        val s = 2f * r // diameter of the circle that contains the arc
        val a = a1 // arc start angle
        val e = (a2 - a1) // arc angle's "extent"
        new Arc2D.Double(x, y, s, s, a, e, Arc2D.OPEN)
    }
           
    val frm = frame(
                    'title->"SQUIB Scenegraph Demo",
                    'visible -> true,
                    'defaultCloseOperation -> JFrame.EXIT_ON_CLOSE,
                    'size -> new Dimension(640,400),
                    'layout -> borderlayout(),
                    contents(
                     scenepanel("scene",
                         'scene ->   group("sub",
                                 scale("sub", 1.0, 1.0, 
                                      group(
                                         image('image->testImage),
                                         translate(50, 50, 
                                                 rotate("square", 1.0,
                                                         shape(
                                                                 'shape -> rectangle(-20,-20,40,40),
                                                                 'mode -> SGAbstractShape.Mode.STROKE_FILL,
                                                                 'fillPaint -> Color.RED,
                                                                 'drawPaint -> Color.ORANGE,
                                                                 'drawStroke -> new BasicStroke(5.0f)
                                                         )
                                                 )
                                         ),
                                     	 text("blah",
                                              'text -> "Blah",
                                              'location -> point(10,20)
                                         ),
                                         translate("button", 10, 30,
                                                 composite("button", 0.75, 
                                                         button('text->"FooBar")
                                                 )
                                         ),
                                         translate(25,75,
                                            rotate(-2.0,
                                               effect(
                                                  'effect -> coloradjust('brightness-> -.25f),
                                                  'child-> group("smiley",
                                                 shape( //face 
                                                         'shape-> new Ellipse2D.Float(-20f, -20f, 40f, 40f),
                                                         'fillPaint -> Color.YELLOW,
                                                         'mode -> SGAbstractShape.Mode.STROKE_FILL,
                                                         'drawStroke -> new BasicStroke(0.15f),
                                                         'drawPaint -> Color.black),
                                                 createFill(new Ellipse2D.Float(-8.5f, -11f, 5f, 8f)),
                                                 createStroke(createArc(4f, P(-14.6, 5.7), P(-10.6, 2.7)), 0.5f),
                                                 createFill(new Ellipse2D.Float(3.5f, -11f, 5f, 8f)),
                                                 createStroke(createArc(4f, P(10.6, 2.7), P(14.6, 5.7)), 0.5f),
                                                 createStroke(createArc(13.5f, P(-12, 5), P(12, 5)), 0.75f),
                                                 createStroke(createArc(13f, P(-12, 5), P(12, 5)), 0.75f)
                                              ))
                                            )
                                         )
                                      )
                                   )
                                 
                          ),
                          'background -> Color.GREEN
                     ) -> "Center",
                     slider("vert", 'minimum->5, 'maximum->100, 'value->5, 'orientation->VERTICAL, 'inverted->true) -> "East",
                     slider("horiz", 'minimum->5, 'maximum->100, 'value->5) -> "South"
                 )
    )
	
    slider.events("vert", sliderValueChanged { value:Int =>
    	scale.id("sub").setScaleY(value / 10.0)
    })
    slider.events("horiz", sliderValueChanged { value:Int =>  
        scale.id("sub").setScaleX(value / 10.0)
    })
    
    group.events("smiley", 'mouseClicked -> { (me:MouseEvent, node:SGNode) => System.out.println("Smiley clicked") },
                           'mouseWheelMoved -> { (me:MouseEvent, node:SGNode) => System.out.println("Wheel moved") }
    )

}
